from django.db import models
from django.contrib.auth.models import User

from django.core.exceptions import ValidationError


def validate_cif(value):
    if ((type(value) != unicode) or (type(value) != str)):
        raise ValidationError(u'CIF-ul trebuie sa fie un sir de caractere')

    if len(value) > 10:
        raise ValidationError(u'CIF-ul trebuie sa aiba maxim 10 caractere')

    if (((type(value) == str) and (value.isdigit() == False)) or
        ((type(value) == unicode) and (value.isdecimal() == False))):
        raise ValidationError(u'CIF-ul trebuie sa fie format doar din cifre')

    cheia = '753217532'

    cc = int(value[-1:])  # extrage cifra control
    value = value[:-1]  # scoate cifra de control din cif

    while len(value) < 9:  # adauga 0 in prefix pana la 9 caractere
        value = '0' + value

    s = 0

    for i in range(len(cheia)):
        s += int(value[i]) * int(cheia[i])

    rest = (s * 10) % 11
    if rest == 10:
        rest = 0

    if rest != cc:
        raise ValidationError(u'CIF-ul nu este valid')


def validate_cnp(value):
    pass


class TimestampedModel(models.Model):
    """
    A timestamped model has 'created', 'updated' and 'user' columns.
    'created' is set to default to the time the record was added.
    'updated' is set to default to the time the record was last updated.
    'user' is to be set by the application depending on which user last updated the record.
    """
    created = models.DateTimeField(verbose_name=u'created at',
        auto_now_add=True,
        editable=False)
    updated = models.DateTimeField(verbose_name=u'updated at',
        auto_now=True,
        editable=False)
    user = models.ForeignKey(User, verbose_name=u'modified by',
        editable=False)

    class Meta:
        abstract = True  # will not create a database table and Django will automatically set this to False on child classes


class County(TimestampedModel):
    name = models.CharField(u'denumire',
        max_length=20,
        unique=True,
        help_text='Denumirea judetului sau a municipiului')


class City(TimestampedModel):
    name = models.CharField(u'denumire',
        max_length=20,
        unique=True,
        help_text='Denumirea orasului')


class Country(TimestampedModel):
    name = models.CharField(u'denumire',
        max_length=20,
        unique=True,
        help_text='Denumirea tarii')


class ContactInformation(TimestampedModel):
    street = models.TextField(u'strada',
        max_length=100,
        help_text='Adresa partenerului')
    county = models.ForeignKey(County,
        verbose_name=u'judet')
    city = models.ForeignKey(City,
        verbose_name=u'oras')
    country = models.ForeignKey(Country,
        verbose_name=u'tara')
    telephone1 = models.CharField('telefon 1',
        max_length=50,
        null=True,
        empty=True,
        help_text='Numar de telefon 1')
    telephone2 = models.CharField('telefon 2',
        max_length=50,
        null=True,
        empty=True,
        help_text='Numar de telefon 2')
    fax = models.CharField('fax',
        max_length=50,
        null=True,
        empty=True,
        help_text='Numar de fax')
    email = models.EmailField('email')


class BusinessPartner(TimestampedModel):
    """
    A BusinessPartner could be a vendor, a client or your own company's subsidiaries.
    """
    name = models.CharField('denumire',
        max_length=50,
        unique=True,
        db_index=True,
        help_text='Denumirea partenerului de afaceri')
    contact_information = models.OneToOneField(ContactInformation,
        verbose_name=u'adresa')
    cif = models.CharField('CIF',
        max_length=10,
        empty=True,
        null=True,
        validators=[validate_cif])
    fiscal_attribute = models.CharField('atribut fiscal',
        max_length=2,
        empty=True,
        null=True,
        help_text='Categoria de platitor de taxe si impozite la bugetul de stat')
    cnp = models.CharField('cod numeric personal',
        max_length=13,
        empty=True,
        null=True,
        validators=[validate_cnp])


class Location(TimestampedModel):
    name = models.CharField(u'denumire',
        max_length=50,
        unique=True,
        help_text='Denumirea comuna a locatiei')
    business_partner = models.ForeignKey(BusinessPartner,
        verbose_name=u'partener de afaceri',
        unique=True,  # any business partner can only have one Location registered
        help_text='Partenerul de afaceri din administrarea proprie, corespunzator acestei locatiei')


class Organization(Location):
    pass


class Workplace(Location):
    pass


class Document(TimestampedModel):
    """
    A Document is an entity related to Business Partners.
    This model holds common fields but specific type of Documents should
    extend this model and add their own specific fields. Django automatically
    constructs a OneToOneField relationship between two models if one inherits
    the other and both are not abstract models. This way, other tables in the
    database can refer to Documents regardless of the document type, while
    document type specific fields are kept in their own table and do not polute
    the Document table with fields that don't relate to the underlying concept
    of what the Document table tries to represent (which is a generic document).
    """
    organization = models.ForeignKey(Organization, editable=False)
    workplace = models.ForeignKey(Workplace, editable=False)

    seller = models.ForeignKey(BusinessPartner,
        verbose_name='vanzator',
        related_name='pos_seller_related')  # TODO check if this produces a self.pos_seller_related_set db Manager
    buyer = models.ForeignKey(BusinessPartner,
        verbose_name='cumparator',
        related_name='pos_buyer_related')  # TODO check if this produces a self.pos_buyer_related_set db Manager

    issued_date = models.DateField('emis la',
        help_text='data emiterii')
    due_date = models.DateField('scadent la',
        help_text='data scadentei')

    payed = models.NullBooleanField('platit?',
        blank=True,
        help_text='Daca documentul a fost achitat')
    notes = models.TextField('note',
        blank=True,
        null=True,
        help_text='Note informative')


class PurchaseInvoice(Document):
    series = models.CharField('serie',
        max_length=10,
        help_text='seria facturii de intrare')
    number = models.DecimalField('numar',
        max_digits=10,
        decimal_places=0,
        unique_for_year='created',
        help_text='numarul facturii de intrare')


class NIR(Document):
    series = models.CharField('serie',
        max_length=10,
        help_text='seria NIR-ului')
    number = models.DecimalField('numar',
        max_digits=10,
        decimal_places=0,
        unique_for_year='created',
        help_text='numarul NIR-ului')

    invoice = models.ForeignKey(Document,
        verbose_name='factura sau avizul',
        help_text='Factura de intrare sau Avizul de insotire a marfii corespunzator NIR-ului')
